# 多进程版本,运算释放内存,使用nonlocal解决作用域的问题
# 使用说明：只要修改《设置搜索范围,价格》即可使用，价格设置精度越高速度越慢，目前执行越2秒
import datetime, time, os
from concurrent.futures import (
    ProcessPoolExecutor,
    as_completed,
    ThreadPoolExecutor,
    wait,
    Future,
)

# from threading import Lock as Lock_t
from multiprocessing import Lock as Lock_p
import numpy, pysnooper

# 设置进程锁
plock = Lock_p()

# 设置目标数值
R1: float = 17_240_300
# 设置搜索范围,价格
A_range = numpy.arange(0.01, 2.4, 0.01)  # armCpu价格
B_range = numpy.arange(0.01, 1.55, 0.01)  # x86Cpu价格
C_range = numpy.arange(0.01, 0.72, 0.01)  # ARM 内存价格
D_range = numpy.arange(0.01, 1.2, 0.01)  # X86 内存价格
E_range = numpy.arange(0.01, 0.12, 0.01)  # 存储价格

# 设置硬件数量
A: int = 8084  # armCpu
B: int = 1034  # x86Cpu
C: float = 21783.55  # ARM 内存
D: float = 2742.13  # X86 内存
E: float = 916019.2  # 存储


def r1_r2_subtraction(r2: float) -> float:
    global R1
    return R1 - r2


# @pysnooper.snoop('src/txt5.log')
def calculate_r2(a: float, b: float, c: float, d: float, e: float) -> dict:
    global A, B, C, D, E
    res: float = (A * a + B * b + C * c + D * d + E * e) * 365
    dictA: dict = {
        "AP": a,
        "BP": b,
        "CP": c,
        "DP": d,
        "EP": e,
        "res": res,  # 本次计算的总值
        "abs": float(abs(r1_r2_subtraction(res))),  # R1-R2后的绝对值
    }
    return dictA


# @pysnooper.snoop('src/txt5.log')
def checker(big_dict: dict, _dict):
    """检查者,对比哪个字典abs值更小并保存"""
    if big_dict["abs"] == 0:
        return _dict
    elif big_dict["abs"] > _dict["abs"]:
        return _dict
    else:
        return big_dict


def comput_for(a: float) -> dict:
    """循环计算主要函数1"""
    dict3 = {"abs": 0}

    def checker(_dict):
        """检查者,对比哪个字典abs值更小并保存"""
        nonlocal dict3
        if dict3["abs"] == 0:
            dict3 = _dict
        elif dict3["abs"] > _dict["abs"]:
            dict3 = _dict

    for b in B_range:
        for c in C_range:
            for d in D_range:
                for e in E_range:
                    _a = calculate_r2(a, b, c, d, e)
                    checker(_a)

    return dict3


os.path


# @pysnooper.snoop('src/txt5.log')
# @pysnooper.snoop('/my/log/file.log')
def main() -> None:
    dict2 = {"abs": 0}

    # @pysnooper.snoop('src/txt5.log')
    def checker2(_d):
        nonlocal dict2
        plock.acquire()
        if dict2["abs"] == 0:
            dict2 = _d
            print(dict2)
        elif dict2["abs"] > _d["abs"]:
            dict2 = _d
            print(dict2)
        plock.release()

    with ProcessPoolExecutor(max_workers=7) as pool:
        ptask_list = [pool.submit(comput_for, i) for i in A_range]
        # wait(ptask_list, return_when="ALL_COMPLETED")
        for _future in as_completed(ptask_list):
            _d = _future.result()
            checker2(_d)

    print("如果程序一开始就看到这段文字说明主线程没有阻塞，程序错误了")
    print("最终结算结果>>>", dict2)


if __name__ == "__main__":
    print("开始运行")
    timeStart = time.time()
    main()
    timeEnd = time.time()
    print("结束运行,总运行秒数为", timeEnd - timeStart)
